"""
技术分析模块
"""
import pandas as pd
import numpy as np
from typing import Dict, Any, Optional
from datetime import datetime


class TechnicalAnalysis:
    """技术分析类"""

    @staticmethod
    def calculate_risk_metrics(stock_data: pd.DataFrame) -> Dict[str, Any]:
        """
        计算风险指标

        Args:
            stock_data: 股票历史数据

        Returns:
            风险指标字典
        """
        if stock_data.empty:
            raise Exception('No data available')

        # 计算日收益率
        stock_data = stock_data.copy()
        stock_data['Daily_Return'] = stock_data['Close'].pct_change()

        # 计算风险指标
        volatility = float(stock_data['Daily_Return'].std()) * np.sqrt(252)  # 年化波动率

        # 计算最大回撤
        rolling_max = stock_data['Close'].expanding().max()
        drawdown = (stock_data['Close'] - rolling_max) / rolling_max
        max_drawdown = float(drawdown.min())

        # 计算Sharpe比率 (假设无风险利率为2%)
        risk_free_rate = 0.02
        annual_return = (float(stock_data['Close'].iloc[-1]) / float(stock_data['Close'].iloc[0])) ** (252/len(stock_data)) - 1
        sharpe_ratio = (annual_return - risk_free_rate) / volatility if volatility != 0 else 0

        return {
            'volatility': round(volatility * 100, 2),  # 百分比
            'max_drawdown': round(max_drawdown * 100, 2),  # 百分比
            'sharpe_ratio': round(float(sharpe_ratio), 3),
            'beta': 1.0,  # 默认值，需要市场数据计算
            'var_95': round(float(stock_data['Daily_Return'].quantile(0.05)) * 100, 2),  # 95% VaR
            'current_price': round(float(stock_data['Close'].iloc[-1]), 2),
            'year_high': round(float(stock_data['High'].max()), 2),
            'year_low': round(float(stock_data['Low'].min()), 2),
            'last_updated': datetime.now().isoformat()
        }

    @staticmethod
    def calculate_chart_data(stock_data: pd.DataFrame) -> Dict[str, Any]:
        """
        计算图表数据

        Args:
            stock_data: 股票历史数据

        Returns:
            图表数据字典
        """
        if stock_data.empty:
            raise Exception('No data available')

        # 准备图表数据
        chart_data = []
        for i in range(len(stock_data)):
            chart_data.append({
                'date': stock_data.index[i].strftime('%Y-%m-%d'),
                'open': round(float(stock_data['Open'].iloc[i]), 2),
                'high': round(float(stock_data['High'].iloc[i]), 2),
                'low': round(float(stock_data['Low'].iloc[i]), 2),
                'close': round(float(stock_data['Close'].iloc[i]), 2),
                'volume': int(stock_data['Volume'].iloc[i])
            })

        # 计算移动平均线
        stock_data = stock_data.copy()
        stock_data['MA20'] = stock_data['Close'].rolling(window=20).mean()
        stock_data['MA50'] = stock_data['Close'].rolling(window=50).mean()

        ma_data = []
        for i in range(len(stock_data)):
            ma20_val = stock_data['MA20'].iloc[i]
            ma50_val = stock_data['MA50'].iloc[i]
            if pd.notna(ma20_val) and pd.notna(ma50_val):
                ma_data.append({
                    'date': stock_data.index[i].strftime('%Y-%m-%d'),
                    'ma20': round(float(ma20_val), 2),
                    'ma50': round(float(ma50_val), 2)
                })

        return {
            'price_data': chart_data,
            'ma_data': ma_data,
            'last_updated': datetime.now().isoformat()
        }

    @staticmethod
    def calculate_investment_recommendation(info: Dict[str, Any], stock_data: pd.DataFrame) -> Dict[str, Any]:
        """
        计算增强版投资建议

        Args:
            info: 股票基本信息
            stock_data: 股票历史数据

        Returns:
            投资建议字典
        """
        if stock_data.empty:
            raise Exception('No data available')

        # 安全地获取和计算指标
        def safe_float(value, default=0):
            if value is None:
                return default
            try:
                return float(value)
            except (ValueError, TypeError):
                return default

        # 计算技术指标
        technical_indicators = TechnicalAnalysis.calculate_technical_indicators(stock_data)

        # 基本面指标
        pe_ratio = safe_float(info.get('trailingPE'))
        pb_ratio = safe_float(info.get('priceToBook'))
        roe = safe_float(info.get('returnOnEquity'))
        dividend_yield = safe_float(info.get('dividendYield'))
        beta = safe_float(info.get('beta'))
        profit_margin = safe_float(info.get('profitMargins'))
        revenue_growth = safe_float(info.get('revenueGrowth'))
        earnings_growth = safe_float(info.get('earningsGrowth'))

        # 治理风险指标
        audit_risk = safe_float(info.get('auditRisk'))
        board_risk = safe_float(info.get('boardRisk'))
        compensation_risk = safe_float(info.get('compensationRisk'))
        share_holder_rights_risk = safe_float(info.get('shareHolderRightsRisk'))
        overall_risk = safe_float(info.get('overallRisk'))

        # 财务健康指标
        total_cash = safe_float(info.get('totalCash'))
        total_debt = safe_float(info.get('totalDebt'))
        total_revenue = safe_float(info.get('totalRevenue'))
        market_cap = safe_float(info.get('marketCap'))
        enterprise_value = safe_float(info.get('enterpriseValue'))

        # 持股结构
        held_percent_insiders = safe_float(info.get('heldPercentInsiders'))
        held_percent_institutions = safe_float(info.get('heldPercentInstitutions'))

        # 估值增强指标
        price_to_sales = safe_float(info.get('priceToSalesTrailing12Months'))
        enterprise_to_revenue = safe_float(info.get('enterpriseToRevenue'))

        # 价格位置分析
        current_price = float(stock_data['Close'].iloc[-1])
        year_high = safe_float(info.get('fiftyTwoWeekHigh'))
        year_low = safe_float(info.get('fiftyTwoWeekLow'))

        # 计算价格位置百分比
        price_position = ((current_price - year_low) / (year_high - year_low)) * 100 if year_high > year_low else 50

        # 波动率计算
        stock_data = stock_data.copy()
        stock_data['Daily_Return'] = stock_data['Close'].pct_change()
        volatility = safe_float(stock_data['Daily_Return'].std() * np.sqrt(252))

        # 综合评分系统 (总分100分)
        score = 50  # 基础分
        signals = []
        detailed_scores = {}

        # 1. 估值分析 (25分)
        valuation_score = 12.5
        if pe_ratio > 0:
            if pe_ratio < 8:
                valuation_score += 5
                signals.append(f"PE比率({pe_ratio:.1f})极低，显著低估")
            elif pe_ratio < 15:
                valuation_score += 3
                signals.append(f"PE比率({pe_ratio:.1f})较低，可能被低估")
            elif pe_ratio > 25:
                valuation_score -= 3
                signals.append(f"PE比率({pe_ratio:.1f})较高，可能被高估")

        if pb_ratio > 0:
            if pb_ratio < 0.8:
                valuation_score += 4
                signals.append(f"PB比率({pb_ratio:.2f})低于1，显著低估")
            elif pb_ratio < 1.5:
                valuation_score += 2
                signals.append(f"PB比率({pb_ratio:.2f})合理")
            elif pb_ratio > 3:
                valuation_score -= 2
                signals.append(f"PB比率({pb_ratio:.2f})偏高")

        detailed_scores['估值'] = min(25, max(0, valuation_score))
        score += valuation_score - 12.5

        # 2. 盈利能力 (20分)
        profitability_score = 10
        if roe > 0:
            if roe > 0.15:
                profitability_score += 5
                signals.append(f"ROE({roe*100:.1f}%)优秀，盈利能力强")
            elif roe > 0.10:
                profitability_score += 3
                signals.append(f"ROE({roe*100:.1f}%)良好")
            elif roe < 0.05:
                profitability_score -= 3
                signals.append(f"ROE({roe*100:.1f}%)较低，盈利能力弱")

        if profit_margin > 0:
            if profit_margin > 0.20:
                profitability_score += 3
                signals.append(f"利润率({profit_margin*100:.1f}%)很高")
            elif profit_margin > 0.10:
                profitability_score += 1
                signals.append(f"利润率({profit_margin*100:.1f}%)合理")

        detailed_scores['盈利能力'] = min(20, max(0, profitability_score))
        score += profitability_score - 10

        # 3. 成长性 (15分)
        growth_score = 7.5
        if earnings_growth > 0:
            if earnings_growth > 0.20:
                growth_score += 4
                signals.append(f"盈利增长({earnings_growth*100:.1f}%)强劲")
            elif earnings_growth > 0.10:
                growth_score += 2
                signals.append(f"盈利增长({earnings_growth*100:.1f}%)稳定")

        if revenue_growth > 0:
            if revenue_growth > 0.15:
                growth_score += 3.5
                signals.append(f"营收增长({revenue_growth*100:.1f}%)良好")
            elif revenue_growth > 0.05:
                growth_score += 1.5
                signals.append(f"营收增长({revenue_growth*100:.1f}%)稳定")

        detailed_scores['成长性'] = min(15, max(0, growth_score))
        score += growth_score - 7.5

        # 4. 财务健康 (15分)
        financial_health_score = 7.5
        if total_cash > 0 and total_debt > 0:
            debt_to_cash = total_debt / total_cash
            if debt_to_cash < 1.5:
                financial_health_score += 4
                signals.append("现金充足，偿债能力强")
            elif debt_to_cash > 3:
                financial_health_score -= 3
                signals.append("债务水平较高，需关注偿债能力")

        if market_cap > 0:
            if market_cap > 1e12:  # 大于1万亿
                financial_health_score += 2
                signals.append("大型公司，抗风险能力强")
            elif market_cap < 1e9:  # 小于10亿
                financial_health_score -= 1
                signals.append("小型公司，风险相对较高")

        detailed_scores['财务健康'] = min(15, max(0, financial_health_score))
        score += financial_health_score - 7.5

        # 5. 治理风险 (10分)
        governance_score = 5
        if overall_risk > 0:
            if overall_risk <= 3:
                governance_score += 3
                signals.append("公司治理风险较低")
            elif overall_risk >= 7:
                governance_score -= 3
                signals.append("公司治理风险较高，需谨慎")

        if held_percent_insiders > 0.3:
            governance_score += 1
            signals.append(f"内部持股比例({held_percent_insiders*100:.1f}%)高，利益一致性较好")
        elif held_percent_insiders < 0.05:
            governance_score -= 1
            signals.append("内部持股比例较低")

        detailed_scores['治理风险'] = min(10, max(0, governance_score))
        score += governance_score - 5

        # 6. 技术面 (15分)
        technical_score = 7.5
        if technical_indicators.get('trend_signal') == 'BULLISH':
            technical_score += 4
            signals.append("技术趋势向上")
        elif technical_indicators.get('trend_signal') == 'BEARISH':
            technical_score -= 2
            signals.append("技术趋势向下")

        if price_position < 20:
            technical_score += 3
            signals.append(f"价格({price_position:.1f}%)接近年内低点")
        elif price_position > 80:
            technical_score -= 2
            signals.append(f"价格({price_position:.1f}%)接近年内高点")

        detailed_scores['技术面'] = min(15, max(0, technical_score))
        score += technical_score - 7.5

        # 确保分数在合理范围
        score = max(0, min(100, score))

        # 综合建议
        if score >= 75:
            recommendation = "强烈买入"
            confidence = "高"
        elif score >= 60:
            recommendation = "买入"
            confidence = "中高"
        elif score >= 45:
            recommendation = "持有"
            confidence = "中等"
        elif score >= 30:
            recommendation = "观望"
            confidence = "中等"
        else:
            recommendation = "卖出"
            confidence = "高"

        return {
            'recommendation': recommendation,
            'confidence': confidence,
            'score': round(score, 1),
            'signals': signals,
            'detailed_scores': {k: round(v, 1) for k, v in detailed_scores.items()},
            'technical_summary': {
                'trend': technical_indicators.get('trend_signal', 'NEUTRAL'),
                'rsi': technical_indicators.get('rsi'),
                'price_position': round(price_position, 1),
                'volatility': round(volatility * 100, 2)
            },
            'fundamental_summary': {
                'pe': round(pe_ratio, 2) if pe_ratio > 0 else None,
                'pb': round(pb_ratio, 2) if pb_ratio > 0 else None,
                'roe': round(roe * 100, 2) if roe > 0 else None,
                'dividend_yield': round(dividend_yield * 100, 2) if dividend_yield > 0 else None
            },
            'warning': "投资有风险，建议结合个人风险承受能力和投资期限做出决策",
            'last_updated': datetime.now().isoformat()
        }

    @staticmethod
    def calculate_technical_indicators(stock_data: pd.DataFrame) -> Dict[str, Any]:
        """
        计算技术分析指标

        Args:
            stock_data: 股票历史数据

        Returns:
            技术指标字典
        """
        if stock_data is None or len(stock_data) == 0:
            return {}

        # 提取价格数据（处理多级列名）
        if len(stock_data.columns) > 0 and isinstance(stock_data.columns[0], tuple):
            ticker = stock_data.columns[0][1]
            close_prices = stock_data[('Close', ticker)].dropna()
            volumes = stock_data[('Volume', ticker)].dropna()
            high_prices = stock_data[('High', ticker)].dropna()
            low_prices = stock_data[('Low', ticker)].dropna()
        else:
            close_prices = stock_data['Close'].dropna()
            volumes = stock_data['Volume'].dropna()
            high_prices = stock_data['High'].dropna()
            low_prices = stock_data['Low'].dropna()

        if len(close_prices) < 20:
            return {}

        try:
            # 基本统计
            current_price = close_prices.iloc[-1]
            price_20d = close_prices.iloc[-20:].mean()
            price_50d = close_prices.iloc[-50:].mean() if len(close_prices) >= 50 else None
            price_200d = close_prices.iloc[-200:].mean() if len(close_prices) >= 200 else None

            # 波动率计算（20日标准差）
            returns = close_prices.pct_change().dropna()
            volatility_20d = returns.iloc[-20:].std() * np.sqrt(252) if len(returns) >= 20 else None

            # RSI计算（14日）
            def calculate_rsi(prices, period=14):
                delta = prices.diff()
                gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
                loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
                rs = gain / loss
                return 100 - (100 / (1 + rs))

            rsi = calculate_rsi(close_prices)
            current_rsi = rsi.iloc[-1] if len(rsi) > 0 else None

            # MACD计算
            def calculate_macd(prices, fast=12, slow=26, signal=9):
                exp1 = prices.ewm(span=fast).mean()
                exp2 = prices.ewm(span=slow).mean()
                macd = exp1 - exp2
                signal = macd.ewm(span=signal).mean()
                return macd, signal

            macd, signal = calculate_macd(close_prices)
            current_macd = macd.iloc[-1] if len(macd) > 0 else None
            current_signal = signal.iloc[-1] if len(signal) > 0 else None
            macd_histogram = current_macd - current_signal if (current_macd is not None and current_signal is not None) else None

            # 布林带计算（20日）
            sma_20 = close_prices.rolling(window=20).mean()
            std_20 = close_prices.rolling(window=20).std()
            upper_band = sma_20 + (std_20 * 2)
            lower_band = sma_20 - (std_20 * 2)
            current_upper = upper_band.iloc[-1] if len(upper_band) > 0 else None
            current_lower = lower_band.iloc[-1] if len(lower_band) > 0 else None
            current_sma = sma_20.iloc[-1] if len(sma_20) > 0 else None

            # 价格相对位置（布林带）
            bb_position = ((current_price - current_lower) / (current_upper - current_lower)) * 100 if (current_upper and current_lower and current_upper > current_lower) else None

            # 支撑位和阻力位（最近3个月的最低/最高）
            recent_high = high_prices.iloc[-63:].max() if len(high_prices) >= 63 else high_prices.max()
            recent_low = low_prices.iloc[-63:].min() if len(low_prices) >= 63 else low_prices.min()

            # 成交量分析
            avg_volume = volumes.iloc[-20:].mean() if len(volumes) >= 20 else None
            current_volume = volumes.iloc[-1] if len(volumes) > 0 else None
            volume_ratio = current_volume / avg_volume if (current_volume and avg_volume and avg_volume > 0) else None

            # 价格动量（1个月、3个月）
            momentum_1m = ((current_price / close_prices.iloc[-22]) - 1) * 100 if len(close_prices) >= 22 else None
            momentum_3m = ((current_price / close_prices.iloc[-63]) - 1) * 100 if len(close_prices) >= 63 else None

            # 趋势判断（基于移动平均线）
            trend_signal = "NEUTRAL"
            if price_20d is not None and price_50d is not None:
                if current_price > price_20d and price_20d > price_50d:
                    trend_signal = "BULLISH"
                elif current_price < price_20d and price_20d < price_50d:
                    trend_signal = "BEARISH"

            # RSI信号
            rsi_signal = "NEUTRAL"
            if current_rsi is not None:
                if current_rsi > 70:
                    rsi_signal = "OVERBOUGHT"
                elif current_rsi < 30:
                    rsi_signal = "OVERSOLD"

            return {
                'current_price': current_price,
                'sma_20d': price_20d,
                'sma_50d': price_50d,
                'sma_200d': price_200d,
                'volatility_20d': volatility_20d,
                'rsi': current_rsi,
                'rsi_signal': rsi_signal,
                'macd': current_macd,
                'macd_signal': current_signal,
                'macd_histogram': macd_histogram,
                'bb_upper': current_upper,
                'bb_lower': current_lower,
                'bb_sma': current_sma,
                'bb_position': bb_position,
                'recent_high': recent_high,
                'recent_low': recent_low,
                'avg_volume_20d': avg_volume,
                'current_volume': current_volume,
                'volume_ratio': volume_ratio,
                'momentum_1m': momentum_1m,
                'momentum_3m': momentum_3m,
                'trend_signal': trend_signal,
                'rsi_overbought_oversold': rsi_signal
            }
        except Exception as e:
            print(f"Error calculating technical indicators: {e}")
            return {}